package com.apes.scm.stock.transfer.service;

import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.account.model.AccountingMethod;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.model.InventoryMode;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.account.account.service.ProductAccountService;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.sal.saleReturn.SaleReturn;
import com.apes.scm.sal.saleReturn.SaleReturnItem;
import com.apes.scm.sal.saleReturn.SaleReturnRepository;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.repository.VoucherRepository;
import com.apes.scm.voucher.service.BusinessType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 分销退货无实物商品转凭证
 */
@Service
public class PickFlowSaleReturnNonphysicalVoucherService extends DomainService {

    @Autowired
    private SaleReturnRepository saleReturnRepository;
    @Autowired
    private ProductAccountService productAccountService;

    public SaleReturn nonphysicalInsertVoucher(SimpleRequest request) {
        SaleReturn saleReturn = request.getO(SaleReturn.class);
        saleReturn = saleReturnRepository.findOne(saleReturn.getId());
        if (!Objects.equals(saleReturn.getState(), "done")) {
            throw new RuntimeException("分销退货单的状态不对，请核对！！！");
        }

        // 原单退货，和无单退货 逻辑不一样
        if (Objects.equals(saleReturn.getOrderType().getCode(), "B")) {
            noOriginCreateVoucher(saleReturn);
            return saleReturn;
        } else {
            createPurchaseReturnVoucher(saleReturn);
        }
        return saleReturn;
    }

    /**
     * 无原单生成返厂凭证
     *
     * @param saleReturn 分销退货
     */
    private void noOriginCreateVoucher(SaleReturn saleReturn) {
        Voucher voucher = getDefaultVoucher(saleReturn);
        List<SaleReturnItem> itemList = getReturnItems(saleReturn); // 获取可退货的明细
        if (itemList.isEmpty()) return;
        voucher.setPartner(SpringManager.getBean(PartyRoleRepository.class).findOne("A00000"));

        // 查找代销合同（目前采购结算按照合同）
        voucher.setVoucherItems(
                itemList.stream().map(
                        item -> {
                            // 无原单不指定供应商和销售批次
                            VoucherItem voucherItem = new VoucherItem();
                            voucherItem.setProduct(item.getProduct());
                            voucherItem.setTax(item.getTax());
                            // 设置为销售的单位以及数量
                            voucherItem.setUom(item.getUom());
                            voucherItem.setProductQty(-1.00 * item.getProductUomQty());
                            voucherItem.setPriceUnit(0);
                            voucherItem.setOriginItemId(item.getId());
                            voucherItem.setSourceItemId(item.getId());
                            voucherItem.setOwner(saleReturn.getCompany());

                            // 库存控制
                            if ("product".equals(item.getProduct().getType())) {
                                extracted(saleReturn, item);
                            }

                            return voucherItem;
                        }).collect(Collectors.toSet()));
        invoke("voucher.create", MapUtil.mapped(voucher));

    }

    private List<SaleReturnItem> getReturnItems(SaleReturn saleReturn) {
        List<SaleReturnItem> itemList;
        if (saleReturn.getLocation().checkProductRuleLocation()) {
            // 判断仓库，带安库的全部退掉，不区分商品是否为实物还是非实物商品
            itemList = new ArrayList<>(saleReturn.getSaleReturnItems());
        } else {
            // 非带安库，只处理非实物商品
            itemList = saleReturn.getSaleReturnItems().stream()
                    .filter(item -> Objects.equals(item.getProduct().getType(), "aut"))
                    .collect(Collectors.toList());
        }
        return itemList;
    }

    /**
     * 有原单分销退货生成返厂凭证
     *
     * @param saleReturn 分销退货
     */
    private void createPurchaseReturnVoucher(SaleReturn saleReturn) {
        // 获取原销售凭证
        Voucher source = SpringManager.getBean(VoucherRepository.class).findOne(
                        JpaDsl.toCriteriaByEq("sourceBusinessType", SaleReturn.class.getSimpleName(), "source", saleReturn.getId(), "voucherType", "CUSTOMER_SALE"))
                .orElseThrow(() -> new RuntimeException("没有找到退货原单：" + saleReturn.getId() + " 的业务凭证！"));
        List<SaleReturnItem> itemList = getReturnItems(saleReturn);     // 获取可退货的明细
        if (itemList.isEmpty()) return;

        //用于查找原销售凭证的批次
        Map<String, VoucherItem> voucherItemMap = source.getVoucherItems().stream().collect(Collectors.toMap(VoucherItem::getSourceItemId, voucherItem -> voucherItem));
        //构建凭证明细
        Set<VoucherItem> voucherItemSet = itemList.stream().map(item -> {
            VoucherItem voucherItem = new VoucherItem();
            voucherItem.setProduct(item.getProduct());
            voucherItem.setOwner(item.getCompany());
            voucherItem.setUom(item.getUom());
            voucherItem.setProductQty(-1.00 * item.getProductUomQty());
            voucherItem.setOriginItemId(String.valueOf(item.getId()));
            voucherItem.setSourceItemId(String.valueOf(item.getId()));

            // 获取原销售批次
            VoucherInventory voucherInventory = SpringManager.getBean(VoucherInventoryRepository.class)
                    .findAll(JpaDsl.toCriteriaByEq("voucher.id", source.getId(), "voucherItem", voucherItemMap.get(item.getId()).getId()))
                    .stream().findFirst().orElse(new VoucherInventory());
            InventoryBatch inventoryBatch = voucherInventory.getInventoryBatch();
            voucherItem.setInventoryBatch(inventoryBatch);
            voucherItem.setPriceUnit(inventoryBatch.getTaxCostPrice());
            voucherItem.setSupplier(inventoryBatch.getSupplier());
            voucherItem.setTax(inventoryBatch.getTax());

            //  增加（减少）冻结数量
            SpringManager.getBean(InventoryService.class).changeFrostQty(inventoryBatch, item.getUom(), item.getProductUomQty(), inventoryBatch.getCompany(),
                    source.getInnerBusinessType(), source.getId(), item.getId(), "生成分销商品返厂凭证");

            // 库存控制
            if ("product".equals(item.getProduct().getType())) {
                extracted(saleReturn, item);
            }

            return voucherItem;
        }).collect(Collectors.toSet());

        // 构建 Model
        Voucher voucher = getDefaultVoucher(saleReturn);
        voucher.setVoucherItems(new HashSet<>(voucherItemSet));
        invoke("voucher.create", MapUtil.mapped(voucher));
    }

    private void extracted(SaleReturn saleReturn, SaleReturnItem saleReturnItem) {
        //写商品库存帐可用数
        productAccountService.setProductAvailable(saleReturnItem.getProduct(), saleReturn.getLocation(), saleReturnItem.getUom(),
                -1 * Math.abs(saleReturnItem.getProductUomQty()), saleReturn.getInnerBusinessType(), saleReturn.getId(),
                saleReturnItem.getId(), "分销退货退工单外协部分", saleReturn.getCompany());

        //写商品库存帐保管数
        productAccountService.setProductCustody(saleReturnItem.getProduct(), saleReturn.getLocation(), saleReturnItem.getUom(),
                -1 * Math.abs(saleReturnItem.getProductUomQty()), saleReturn.getInnerBusinessType(), saleReturn.getId(),
                saleReturnItem.getId(), "分销退货退工单外协部分", saleReturn.getCompany());
    }

    /**
     * 构建凭证主体
     *
     * @param saleReturn 分销退货
     * @return 凭证
     */
    private Voucher getDefaultVoucher(SaleReturn saleReturn) {
        Voucher voucher = new Voucher();
        voucher.setReturned(true);
        voucher.setCompany(saleReturn.getCompany());
        voucher.setBusinessType(BusinessType.PURCHASE_RETURN);
        voucher.setDept(saleReturn.getDept());
        voucher.setClerk(saleReturn.getClerk());
        voucher.setPartner(saleReturn.getCompany().getParty().getPatyRoleByType("Supplier"));
        voucher.setScene(saleReturn.getScene());
        voucher.setOrigin(saleReturn.getId());
        voucher.setOriginBusinessType(saleReturn.getInnerBusinessType());
        voucher.setSource(saleReturn.getId());
        voucher.setSourceBusinessType(saleReturn.getInnerBusinessType());

        // 如果是定损来源的，并且是代销带安的，类似于 拖车救援 的情况，将库存模式设置为：代销就可以退货了
        voucher.setInventoryMode(InventoryMode.IM_OWN);      //设置库存模式：自有
        voucher.setAccountingMethod(AccountingMethod.AM_PURCHASE);       // 核算方式：经销
        return voucher;
    }

}
